from io import BytesIO

from django.utils import timezone
from django.core.exceptions import ObjectDoesNotExist
from django.db import DatabaseError
from django.utils.encoding import escape_uri_path
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.exceptions import ValidationError
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Questions
from .serializers import QuestionsSerializer, QuestionsListSerializer, QuestionsCreateUpdateSerializer
from rest_framework.permissions import AllowAny, IsAuthenticated
from django.http import JsonResponse, HttpResponse

from ..UserManagement.models import User
from ..utils.pageNumberPagination import CustomPageNumberPagination
from ..utils.response_utils import api_response, ResponseCode

from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework.parsers import MultiPartParser, FormParser
import pandas as pd


class QuestionList(APIView):
    """
    查询所有试题列表
    """
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    pagination_class = CustomPageNumberPagination

    @swagger_auto_schema(
        operation_description="查询所有试题列表，支持按类型、分类、难度和标题进行筛选",
        manual_parameters=[
            openapi.Parameter('type', openapi.IN_QUERY, description="试题类型", type=openapi.TYPE_STRING,
                              enum=['single', 'multiple', 'judge', 'short']),
            openapi.Parameter('classify', openapi.IN_QUERY, description="试题分类", type=openapi.TYPE_STRING),
            openapi.Parameter('difficulty', openapi.IN_QUERY, description="试题难度", type=openapi.TYPE_STRING,
                              enum=['easy', 'medium', 'hard']),
            openapi.Parameter('topic', openapi.IN_QUERY, description="试题标题", type=openapi.TYPE_STRING),
        ],
        responses={
            200: QuestionsListSerializer(many=True),
            400: "请求参数错误",
            500: "服务器内部错误"
        },
        tags=['试题管理']
    )
    def get(self, request):
        try:
            # 获取分页参数
            page = request.query_params.get("pageNo", 1)
            page_size = request.query_params.get("pageSize", 10)
            qst_type = request.query_params.get("type")
            classify = request.query_params.get("classify")
            difficulty = request.query_params.get("difficulty")
            topic = request.query_params.get("topic")

            # 查询所有问题
            questions = Questions.objects.all().order_by("topic")

            if qst_type:
                questions = questions.filter(type=qst_type)
            if classify:
                questions = questions.filter(classify=classify)
            if difficulty:
                questions = questions.filter(difficulty=difficulty)
            if topic:
                questions = questions.filter(topic__icontains=topic)

            if not questions:
                return api_response(ResponseCode.SUCCESS, "没有找到符合条件的试题", [])

            paginator = CustomPageNumberPagination()
            paginator.page_size = int(page_size)  # 每页的条数
            paginator.page_query_param = 'pageNo'  # 页码的参数名
            paginator.page_size_query_param = 'page_size'  # 每页数据条数的参数名

            result_page = paginator.paginate_queryset(questions, request)
            serializer = QuestionsListSerializer(result_page, many=True)
            paginated_response = paginator.get_paginated_response(serializer.data)

            return api_response(ResponseCode.SUCCESS, "查询成功", paginated_response.data)
        except ValidationError as e:
            return api_response(ResponseCode.BAD_REQUEST, f"请求参数错误: {str(e)}")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"服务器内部错误: {str(e)}")


class GetQuestions(APIView):
    """
    查询试题列表接口（不分页）
    """
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="获取试题列表",
        manual_parameters=[
            openapi.Parameter('type', openapi.IN_QUERY, description="试题类型", type=openapi.TYPE_STRING,
                              enum=['single', 'multiple', 'judge', 'short']),
        ],
        responses={200: QuestionsListSerializer(many=True),
                   400: "试题列表为空"},  # 返回所有试题的列表
        tags=['试题管理']
    )
    def get(self, request):
        try:
            qst_type = request.query_params.get("type")
            questions = Questions.objects.all()
            if qst_type:
                questions = questions.filter(type=qst_type)
            if not questions:
                return api_response(ResponseCode.SUCCESS, "没有找到符合条件的试题", [])
            serializer = QuestionsListSerializer(questions, many=True)  # 序列化多个试题

            return api_response(ResponseCode.SUCCESS, "查询成功", serializer.data)

        except Exception as e:
            # 捕获所有其他异常
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"服务器内部错误: {str(e)}")


class QuestionDetail(APIView):
    """
    根据id查询试题信息
    """
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="根据试题id查询信息",
        manual_parameters=[
            openapi.Parameter('id', openapi.IN_QUERY, description="试题id", type=openapi.TYPE_STRING),
        ],
        responses={
            200: QuestionsSerializer(),
            404: "未找到信息",
            500: "服务器内部错误"
        },
        tags=['试题管理']
    )
    def get(self, request):
        qst_id = request.query_params.get("id")
        try:
            question = Questions.objects.get(id=qst_id)
        except ObjectDoesNotExist:
            return api_response(ResponseCode.NOT_FOUND, "未找到该试题")

        serializer = QuestionsSerializer(question)
        return api_response(ResponseCode.SUCCESS, "查询成功", serializer.data)


class QuestionUpdate(APIView):
    """
    修改试题接口
    """
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="修改试题接口",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'id': openapi.Schema(type=openapi.TYPE_STRING, description="试题id"),
                'topic': openapi.Schema(type=openapi.TYPE_STRING, description="试题标题"),
                'type': openapi.Schema(type=openapi.TYPE_STRING, description="试题类型",
                                       enum=['single', 'multiple', 'judge', 'short']),
                'classify': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_STRING),
                    description="试题分类（数组）"
                ),
                'options': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_STRING),
                    description="试题选项（数组）"
                ),
                'answer': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_INTEGER),
                    description="试题答案（数组）"
                ),
                'keywords': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_STRING),
                    description="简答题答案（关键字，数组）"
                ),
                'difficulty': openapi.Schema(type=openapi.TYPE_STRING, description="试题难度",
                                             enum=['easy', 'medium', 'hard']),
            },
        ),
        responses={
            200: openapi.Response('修改成功', QuestionsCreateUpdateSerializer),
            400: "请求数据无效或题目未找到"
        },
        tags=['试题管理']
    )
    def put(self, request):
        """
        修改题目接口
        """
        try:
            qst_id = request.data.get("id")
            question = Questions.objects.get(id=qst_id)
        except ObjectDoesNotExist:
            return api_response(ResponseCode.BAD_REQUEST, "未找到该题目")

        serializer = QuestionsCreateUpdateSerializer(question, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return api_response(ResponseCode.SUCCESS, "修改题目成功", serializer.data)
        return api_response(ResponseCode.BAD_REQUEST, "修改失败", serializer.errors)


class QuestionDelete(APIView):
    """
    删除题目接口
    """
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="删除试题接口",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'ids': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_STRING),
                    description='试题ID列表，删除多个试题'
                ),
            },
        ),
        responses={
            200: "删除成功",
            400: "未找到该题目"
        },
        tags=['试题管理']
    )
    def delete(self, request):
        """
        删除题目接口
        """
        try:
            # 获取请求中的题目 ID 列表
            qst_ids = request.data.get('ids', [])

            if not qst_ids:
                return api_response(ResponseCode.BAD_REQUEST, "请求数据无效，必须提供题目ID列表")

            # 查找题目，删除不存在的题目ID
            questions_to_delete = Questions.objects.filter(id__in=qst_ids)
            if questions_to_delete.count() == 0:
                return api_response(ResponseCode.NOT_FOUND, "未找到题目")

            # 删除找到的题目
            questions_to_delete.delete()

            return api_response(ResponseCode.SUCCESS, "删除成功")
        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, f"服务器内部错误: {str(e)}")


class QuestionCreate(APIView):
    """
    创建新的试题接口
    """
    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="创建新的试题",
        request_body=openapi.Schema(
            type=openapi.TYPE_OBJECT,
            properties={
                'topic': openapi.Schema(type=openapi.TYPE_STRING, description="试题标题"),
                'type': openapi.Schema(type=openapi.TYPE_STRING, description="试题类型",
                                       enum=['single', 'multiple', 'judge', 'short']),
                'classify': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_STRING),
                    description="试题分类（数组）"
                ),
                'options': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_STRING),
                    description="试题选项（数组）"
                ),
                'answer': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_INTEGER),
                    description="试题答案（数组）"
                ),
                'keywords': openapi.Schema(
                    type=openapi.TYPE_ARRAY,
                    items=openapi.Schema(type=openapi.TYPE_STRING),
                    description="简答题答案（关键字，数组）"
                ),
                'difficulty': openapi.Schema(type=openapi.TYPE_STRING, description="试题难度",
                                             enum=['easy', 'medium', 'hard']),
                'user_id': openapi.Schema(type=openapi.TYPE_STRING, description="用户id"),
            },
        ),
        responses={
            200: openapi.Response('创建成功', QuestionsCreateUpdateSerializer),
            400: "请求数据无效"
        },
        tags=['试题管理']
    )
    def post(self, request):
        """
        创建新的试题
        """

        serializer = QuestionsCreateUpdateSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return api_response(ResponseCode.SUCCESS, "添加成功")
        return api_response(ResponseCode.BAD_REQUEST, "添加失败", serializer.errors)


class QuestionImport(APIView):
    """
        批量导入题目
    """

    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]
    parser_classes = (MultiPartParser, FormParser)  # 指定使用 MultiPartParser 和 FormParser 解析器

    @swagger_auto_schema(
        operation_description="上传试题",
        manual_parameters=[
            openapi.Parameter(
                name='file',
                in_=openapi.IN_FORM,
                type=openapi.TYPE_FILE,
                description='Excel文件路径',
                required=True,
            ),
        ],
        responses={200: '添加成功', 400: '添加失败'},
        tags=['试题管理']
    )
    def post(self, request):
        file = request.FILES.get('file')
        if not file:
            return api_response(ResponseCode.BAD_REQUEST, "未上传试题")

        try:
            df = pd.read_excel(file)
            print(df)
            for index, row in df.iterrows():
                topic = str(row['试题标题']).strip()
                type = str(row['试题类型']).strip()
                classify = str(row['考试类别']).strip()
                if type == 'short':
                    options = None
                    answer = None
                    keywords = str(row['关键字']).strip()
                else:
                    options = str(row['试题选项']).strip()
                    answer = str(row['试题参考答案']).strip()
                    keywords = None

                difficulty = str(row['试题难度']).strip()
                created_user = User.objects.filter(id=request.user.id).first()
                created_at = timezone.now()

                question_profile = Questions.objects.filter(topic=topic).first()
                if question_profile:
                    return api_response(ResponseCode.BAD_REQUEST, f"试题标题{topic}重复")


                question = Questions.objects.create(topic=topic, options=options, answer=answer, type=type,
                                         difficulty=difficulty, classify=classify, keywords=keywords,
                                         created_user=created_user, created_at=created_at)

                if not question:
                    return api_response(ResponseCode.BAD_REQUEST, f"{topic}添加失败")

            return api_response(ResponseCode.SUCCESS, "添加成功")
        except Exception as e:
            return api_response(ResponseCode.BAD_REQUEST, f"添加失败: {str(e)}")


class QuestionsExport(APIView):
    """
    导出所有试题数据为 Excel 文件
    """

    authentication_classes = [JWTAuthentication]
    permission_classes = [IsAuthenticated]

    @swagger_auto_schema(
        operation_description="导出所有试题数据为 Excel 文件",
        responses={
            200: openapi.Response(
                description="成功导出试题数据",
                examples={
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {
                        "file": "http://example.com/download/questions_data.xlsx"
                    }
                }
            ),
            500: openapi.Response(
                description="服务器内部错误",
                examples={
                    "application/json": {
                        "code": 500,
                        "message": "导出失败，系统错误"
                    }
                }
            ),
        },
        tags=["试题管理"]
    )
    def get(self, request, *args, **kwargs):
        try:
            # 查询所有试题数据
            questions = Questions.objects.all()

            if not questions:
                return api_response(ResponseCode.NOT_FOUND, "没有试题数据可导出")

            # 使用 pandas 创建 DataFrame，方便导出为 Excel
            data = []

            for question in questions:
                answer_list = []
                if question.type in ['single', 'multiple', 'judge']:
                    options = question.get_options()
                    answer = question.get_answer().split(';')
                    for i in answer:
                        index = int(i)
                        if 0 <= index < len(options):
                            answer_list.append(options[index])
                data.append({
                    "试题标题": question.topic,
                    "试题选项": question.options,
                    "试题答案": ';'.join(answer_list),
                    "简答答案（关键字）": question.keywords,
                    "试题类型": dict(Questions.TYPE_CHOICES).get(question.type),
                    "考试类别": question.classify,
                    "难易程度": dict(Questions.DIFFICULTY_CHOICES).get(question.difficulty),
                    "创建人": question.created_user.username if question.created_user else '',
                    # "创建时间": question.created_at.replace(tzinfo=None) if question.created_at else '',
                    "创建时间": question.created_at.strftime('%Y-%m-%d %H:%M:%S') if question.created_at else '',
                    "更新人": question.updated_user.username if question.updated_user else '',
                    "更新时间": question.updated_at.strftime('%Y-%m-%d %H:%M:%S') if question.updated_at else '',
                })

            # 将数据转换为 pandas DataFrame
            df = pd.DataFrame(data)

            # 将 DataFrame 导出为 Excel 文件（内存中）
            file_stream = BytesIO()
            with pd.ExcelWriter(file_stream, engine='xlsxwriter') as writer:
                df.to_excel(writer, index=False, sheet_name='Questions Data')

            # 返回 Excel 文件流
            file_stream.seek(0)

            # 设置响应头，确保文件作为附件下载
            response = HttpResponse(file_stream,
                                    content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
            file_name = "questions_data.xlsx"
            response['Content-Disposition'] = f"attachment; filename*=UTF-8''{escape_uri_path(file_name)}"

            # 返回文件流
            return response

        except DatabaseError:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, "数据库错误，无法查询试题数据")

        except Exception as e:
            return api_response(ResponseCode.INTERNAL_SERVER_ERROR, "导出失败，系统错误", str(e))